package com.glink.manage.service.Impl;

import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.glink.common.contants.BaseCodeConstants;
import com.glink.common.exception.GeneralSimpleException;
import com.glink.manage.domain.ConstructionWorkUnitRelaBean;
import com.glink.manage.domain.PersonAccessRelaBean;
import com.glink.manage.domain.PersonManageBean;
import com.glink.manage.dto.person.PersonAccessCycleSaveDTO;
import com.glink.manage.dto.person.PersonAccessIdDTO;
import com.glink.manage.dto.person.PersonAccessPageDTO;
import com.glink.manage.mapper.PersonAccessRelaMapper;
import com.glink.manage.service.*;
import com.glink.manage.vo.person.PersonAccessPageVO;
import com.glink.manage.vo.temporaryadmission.TemporaryAdmissionCheckWorkVO;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author  qiushaoshan
 * @since 2025-01-16
 */
@Service
@Slf4j
public class PersonAccessRelaServiceImpl extends ServiceImpl<PersonAccessRelaMapper, PersonAccessRelaBean> implements PersonAccessRelaService {

    @Autowired
    private UserService userService;
    
    @Autowired
    private ConstructionWorkService constructionWorkService;
    
    @Autowired
    @Lazy
    private ConstructionWorkUnitRelaService constructionWorkUnitRelaService;
    
    @Autowired
    @Lazy
    private PersonManageService personManageService;
    
    /**
     * 分页查询准入
     *
     * @param dto 分页查询条件
     * @return 准入工程
     */
    @Override
    public IPage<PersonAccessPageVO> pageByAccess(PersonAccessPageDTO dto) throws GeneralSimpleException {
        IPage<PersonAccessRelaBean> iPage = new Page<>(dto.getPage(), dto.getSize());

        IPage<PersonAccessRelaBean> accessRelaBeanIPage = this.lambdaQuery()
                .eq(PersonAccessRelaBean::getPersonId, dto.getPersonObjId())
                .orderByDesc(PersonAccessRelaBean::getCreateTime)
                .orderByDesc(PersonAccessRelaBean::getObjId)
                .page(iPage);

        IPage<PersonAccessPageVO> pageVOIPage = new Page<>(accessRelaBeanIPage.getCurrent(), accessRelaBeanIPage.getSize(), accessRelaBeanIPage.getTotal());
        List<PersonAccessPageVO> pageVOList = Lists.newArrayList();
        if(CollectionUtils.isNotEmpty(accessRelaBeanIPage.getRecords())) {
            List<String> workIdList = Lists.newArrayList();
            boolean generalContractingUnit = userService.checkGeneralContractingUnit();
            if(generalContractingUnit){
                workIdList = constructionWorkService.findGeneralContractingUnitAccessWorkId();
                workIdList = workIdList == null ? Lists.newArrayList() : workIdList;
            }

            List<String> finalWorkIdList = workIdList;
            accessRelaBeanIPage.getRecords().forEach(accessRelaBean -> {
                PersonAccessPageVO accessPageVO = new PersonAccessPageVO();
                accessPageVO.setObjId(accessRelaBean.getObjId());
                accessPageVO.setConstructionWorkObjId(accessRelaBean.getConstructionWorkObjId());
                accessPageVO.setCycleStart(accessRelaBean.getCycleStart());
                accessPageVO.setCycleEnd(accessRelaBean.getCycleEnd());
                if(StringUtils.isNotBlank(accessRelaBean.getConstructionWorkObjId())){
                    accessPageVO.setConstructionWorkObjName(constructionWorkService.findNameByObjId(accessRelaBean.getConstructionWorkObjId()));
                }
                
                if(finalWorkIdList.contains(accessRelaBean.getConstructionWorkObjId())){
                    accessPageVO.setIfGeneralContracting(BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode01);
                }else{
                    accessPageVO.setIfGeneralContracting(BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02);
                }
                
                pageVOList.add(accessPageVO);
            });
            pageVOIPage.setRecords(pageVOList);
        }
        return pageVOIPage;
    }

    /**
     * 删除准入工程
     *
     * @param dto 删除条件
     * @return 删除状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean delAccessWork(PersonAccessIdDTO dto) {
        PersonAccessRelaBean personAccessRelaBean = this.lambdaQuery()
                .eq(PersonAccessRelaBean::getObjId, dto.getAccessObjId())
                .one();
        if(Objects.nonNull(personAccessRelaBean)){
            return removeById(dto.getAccessObjId());   
        }else{
            return false;
        }
    }

    /**
     * 更新准入工程周期
     *
     * @param dto 更新信息
     * @return 更新状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean updateAccessCycle(PersonAccessCycleSaveDTO dto) throws GeneralSimpleException {
        PersonAccessRelaBean personAccessRelaBean = this.lambdaQuery().eq(PersonAccessRelaBean::getObjId, dto.getAccessObjId()).one();
        if(Objects.nonNull(personAccessRelaBean)){
            String constructionWorkObjId = personAccessRelaBean.getConstructionWorkObjId();
            
            PersonManageBean personManageBean = personManageService.getById(personAccessRelaBean.getPersonId());
            if(Objects.nonNull(personManageBean)){
                String orgId = personManageBean.getOrgId();

                Integer count = constructionWorkUnitRelaService.lambdaQuery().eq(ConstructionWorkUnitRelaBean::getConstructionWorkObjId, constructionWorkObjId)
                        .eq(ConstructionWorkUnitRelaBean::getParticipatingUnitObjId, orgId).count();
                if(Objects.isNull(count) || count == 0){
                    throw new GeneralSimpleException("403002", constructionWorkService.findNameByObjId(constructionWorkObjId));   
                }
            }

            personAccessRelaBean.setCycleStart(dto.getCycleStart());
            personAccessRelaBean.setCycleEnd(dto.getCycleEnd());
            
            return updateById(personAccessRelaBean);
        }else{
            return false;
        }
    }

    /**
     * 删除准入
     *
     * @param constructionWorkObjId  工程
     * @param participatingUnitObjId 参建单位
     * @param nowDate                当前时间
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean delAccessByWorkObjIdAndUnitObjIdAndCycleStartGt(String constructionWorkObjId, String participatingUnitObjId, String nowDate) {
        this.baseMapper.delAccessByWorkObjIdAndUnitObjIdAndCycleStartGt(constructionWorkObjId, participatingUnitObjId, nowDate);
        return true;
    }

    /**
     * 更新准入
     *
     * @param constructionWorkObjId  工程
     * @param participatingUnitObjId 参建单位
     * @param nowDate                当前时间
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateAccessCycleEndByWorkObjIdAndUnitObjIdAndCycleStartGtAndCycleEndLt(String constructionWorkObjId, String participatingUnitObjId, String nowDate) {
        this.baseMapper.updateAccessCycleEndByWorkObjIdAndUnitObjIdAndCycleStartGtAndCycleEndLt(constructionWorkObjId, participatingUnitObjId, nowDate);
    }

    /**
     * 根据工程ID查询未同步的人员ID
     *
     * @param constructionWorkObjId 工程ID
     * @return 人员ID
     */
    @Override
    public Set<Integer> findPersonIdByWorkIdAndNotSync(String constructionWorkObjId) {
        return this.baseMapper.findPersonIdByWorkIdAndNotSync(constructionWorkObjId);
    }

    /**
     * 根据人员信息查询准入工程
     *
     * @param personObjId 人员信息
     * @return 准入工程ID
     */
    @Override
    public List<String> findWorkIdByPersonId(String personObjId) {
        List<PersonAccessRelaBean> accessRelaBeanList = this.lambdaQuery().eq(PersonAccessRelaBean::getPersonId, personObjId).list();
        if(CollectionUtils.isNotEmpty(accessRelaBeanList)){
            return accessRelaBeanList.stream().map(PersonAccessRelaBean::getConstructionWorkObjId).collect(Collectors.toList());
        }
        return null;
    }

    /**
     * 查询人员准入记录
     *
     * @param personIdList 人员ID
     * @param dateTime     时间
     * @return 准入信息
     */
    @Override
    public List<PersonAccessRelaBean> findAccessInfoByPersonIdInAndCycleEndGeAndWorkId(List<String> personIdList, DateTime dateTime, String workId) {
        return this.lambdaQuery().in(PersonAccessRelaBean::getPersonId, personIdList)
                .ge(PersonAccessRelaBean::getCycleEnd, dateTime)
                .eq(PersonAccessRelaBean::getConstructionWorkObjId, workId)
                .list();
    }

    /**
     * 查询工程准入信息
     *
     * @param personIdList          人员ID
     * @param constructionWorkObjId 工程
     * @return 准入信息
     */
    @Override
    public List<TemporaryAdmissionCheckWorkVO> findWorkAccessByPersonIdInAndConstructionWorkObjId(List<String> personIdList, String constructionWorkObjId) {
        List<PersonAccessRelaBean> accessRelaBeanList = this.lambdaQuery().in(PersonAccessRelaBean::getPersonId, personIdList)
                .eq(PersonAccessRelaBean::getConstructionWorkObjId, constructionWorkObjId)
                .list();
        List<TemporaryAdmissionCheckWorkVO> checkWorkVOList = Lists.newArrayList();
        if(CollectionUtils.isNotEmpty(accessRelaBeanList)){
            accessRelaBeanList.forEach(accessRelaBean -> {
                TemporaryAdmissionCheckWorkVO checkWorkVO = new TemporaryAdmissionCheckWorkVO();
                checkWorkVO.setIfTemporary(BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02);
                checkWorkVO.setCycleStart(accessRelaBean.getCycleStart());
                checkWorkVO.setCycleEnd(accessRelaBean.getCycleEnd());
                checkWorkVOList.add(checkWorkVO);
            });
        }

        return checkWorkVOList;
    }

    /**
     * 查询准入的工程ID
     *
     * @param personId 人员ID
     * @param dateTime 当前时间
     * @return 工程ID
     */
    @Override
    public List<String> findWorkIdByPersonIdAndCycleStartGeAndCycleEndLe(String personId, DateTime dateTime) {
        List<PersonAccessRelaBean> accessRelaBeanList = this.lambdaQuery()
                .eq(PersonAccessRelaBean::getPersonId, personId)
                .le(PersonAccessRelaBean::getCycleStart, dateTime)
                .ge(PersonAccessRelaBean::getCycleEnd, dateTime)
                .list();
        if(CollectionUtils.isNotEmpty(accessRelaBeanList)){
            return accessRelaBeanList.stream().map(PersonAccessRelaBean::getConstructionWorkObjId).collect(Collectors.toList());
        }
        return null;
    }
}
